﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using VDataAdapter;
using VDataAdapter.BlockingQueue;
using VDataAdapter.EventManagement;
using VDataAdapter.QueueManagement;
using VDataAdapter.Communication;

namespace VDataAdapter.WorkerManagement
{
    //General interface for worker scheduler
    public interface IWorkerScheduler
    {
        List<Worker> scheduleWorkers(IEventProviderQueue providerQueue, VDataCommunicator comm);
    }


    //VDataWorkerScheduler
    //Start worker in specific order
    class VDataWorkerScheduler : IWorkerScheduler
    {
        /// <summary>
        /// This method schedual all wokers in a specified order
        /// 
        /// 1. FirstTimeWorker
        /// 2. TransactionWorker
        /// 3. PutThroughTransationWorker
        /// 
        /// 4. StockWorker
        /// 4. PutThroughTopPriceWorker
        /// 
        /// </summary>
        public List<Worker> scheduleWorkers(IEventProviderQueue eQueue, VDataCommunicator comm)
        {
            string name = Thread.CurrentThread.Name;

            List<Worker> workers = new List<Worker>();

            ManualResetEvent level1DoneFlag = new System.Threading.ManualResetEvent(false);
            ManualResetEvent level2DoneFlag = new System.Threading.ManualResetEvent(false);
            ManualResetEvent level3DoneFlag = new System.Threading.ManualResetEvent(false);

            //start firstTimeWorker
            workers.Add(scheduleFirstTimeWorker(name,eQueue, comm, level1DoneFlag));

            //start transactionWorker
            workers.Add(scheduleTransationWorker(name, eQueue, comm, level1DoneFlag, level2DoneFlag));

            // @Chau: this can be wrong, PutThroughTrasnaction may occur through out the day
            // so it does not have signal StockWorker & PutThroughWorker
            //start putThroughtTransactionWorker
            workers.Add(schedulePutThroughTransationWorker(name, eQueue, comm, level2DoneFlag, level3DoneFlag));

            workers.Add(scheduleMarketInfoWorker(name, eQueue, comm, level2DoneFlag));

            //start stockWorker and putThroughTopPriceWorker
            workers.Add(scheduleStockWorker(name, eQueue, comm, level2DoneFlag));
            workers.Add(schedulePutThroughTopPriceWorker(name, eQueue, comm, level2DoneFlag));

            return workers;
        }

        //This schedual first time worker to fetch the intial data pack
        private Worker scheduleFirstTimeWorker(string parentName,IEventProviderQueue eQueue,VDataCommunicator comm, ManualResetEvent doneFlag)
        {
            Worker firstTimeWorker = new FirstTimeWorker(parentName, doneFlag, comm, eQueue);
            
            return firstTimeWorker;
        }

        private Worker scheduleMarketInfoWorker(string parentName, IEventProviderQueue eQueue, VDataCommunicator comm, ManualResetEvent waitFlag)
        {
            Worker marketInfoWorker = new MarketInfoWorker(parentName, waitFlag, comm, eQueue);
            return marketInfoWorker;
        }

        //This schedual transaction worker to fetch the intial data pack
        private Worker scheduleTransationWorker(string parentName,IEventProviderQueue eQueue, VDataCommunicator comm, ManualResetEvent waitFlag, ManualResetEvent doneFlag)
        {
            Worker transactionWorker = new TransactionWorker(parentName,waitFlag, doneFlag, comm, eQueue);

            return transactionWorker;
        }

        private Worker schedulePutThroughTransationWorker(string parentName, IEventProviderQueue eQueue, VDataCommunicator comm, ManualResetEvent waitFlag, ManualResetEvent doneFlag)
        {
            Worker putThroughTransationWorker = new PutThroughTransactionWorker(parentName, waitFlag, comm, eQueue);

            return putThroughTransationWorker;
        }

        private Worker scheduleStockWorker(string parentName,IEventProviderQueue eQueue, VDataCommunicator comm, ManualResetEvent waitFlag)
        {
            Worker stockWorker = new StockWorker(parentName,waitFlag, comm, eQueue);

            return stockWorker;
        }

        private Worker schedulePutThroughTopPriceWorker(string parentName, IEventProviderQueue eQueue, VDataCommunicator comm, ManualResetEvent waitFlag)
        {
            Worker putThroughTopPriceWorker = new PutThroughWorker(parentName,waitFlag, comm, eQueue);

            return putThroughTopPriceWorker;
        }
    }
}
